package main

import (
	"fmt"
	"strconv"
	"strings"
	"unicode/utf8"
)

func main() {
	//字符串
	//1.定义字符串
	var s1 string
	s1 = "你好"
	fmt.Printf("s1: %T,%s\n", s1, s1)

	s2 := `反引号输出
可以直接换行`
	fmt.Printf("s2: %T,%s\n", s2, s2)

	//字符串中的每个字节，以及整个字符串的长度：
	var st = "中国人"
	fmt.Printf("the length of s = %d\n", len(st)) // 9
	for i := 0; i < len(st); i++ {
		fmt.Printf("0x%x ", st[i]) // 0xe4 0xb8 0xad 0xe5 0x9b 0xbd 0xe4 0xba 0xba
	}
	fmt.Printf("\n")

	//通过字符序列的视角来看字符串
	var su = "中国人"
	fmt.Println("the character count in s is", utf8.RuneCountInString(su)) // 3
	for _, c := range su {
		fmt.Printf("0x%x ", c) // 0x4e2d 0x56fd 0x4eba
	}
	fmt.Printf("\n")

	//2.区别：'A',"A"
	v1 := 'A'
	v2 := "A"
	fmt.Printf("v1: %T,%d\n", v1, v1) //v1: int32,65
	fmt.Printf("v2: %T,%s\n", v2, v2) //v2: string,A

	v3 := '中'
	fmt.Printf("v3: %T,%d,%c,%q\n", v3, v3, v3, v3) //v3: int32,20013,中,'中'

	//3.转义字符
	fmt.Println("\"HelloWorld\"") //"HelloWorld"
	fmt.Println("Hello\nWor\tld")
	fmt.Println(`He"lloWor"ld`) //He"lloWor"ld
	fmt.Println("Hello`Wor`ld") //Hello`Wor`ld

	//遍历字符串
	var str string = "hello"
	for i := 0; i < len(str); i++ {
		fmt.Printf("%c - ", str[i]) //h - e - l - l - o -
	}
	fmt.Println()
	for k, v := range str {
		fmt.Printf("%d = %c \n", k, v)
	}

	//string 的 byte 数组可以存放任何数据
	var s string
	fmt.Println(s) //初始化为默认零值""
	s = "hello"
	fmt.Println(len(s))
	//s[1] = '3' //string是不可变的byte slice
	//s = "\xE4\xB8\xA5" //可以存储任何二进制数据
	s = "\xE4\xBA\xBB\xFF"
	fmt.Println(s)
	fmt.Println(len(s))
	s = "中"
	fmt.Println(len(s)) //是byte数

	c := []rune(s)
	fmt.Println(len(c))
	//	fmt.Println("rune size:", unsafe.Sizeof(c[0]))
	fmt.Printf("中 unicode %x \n", c[0]) //中 unicode 4e2d
	fmt.Printf("中 UTF8 %x \n", s)       //中 UTF8 e4b8ad

	//字符串是字节的集合
	slice1 := []byte{65, 66, 67, 68, 69}
	s3 := string(slice1) //根据一个字节切片，构建字符串
	fmt.Println(s3)      //ABCDE

	s4 := "abcdef"
	slice2 := []byte(s4) //根据字符串，获取对应的字节切片
	fmt.Println(slice2)  //[97 98 99 100 101 102]

	//字符串不能修改
	fmt.Println(s4)
	//s4[2] = 'B' //错误

	//字节长度：和编码无关，用 len(str)获取
	fmt.Println(len("ab")) //2
	fmt.Println(len("你好")) //6

	//字符数量：和编码有关，用编码库来计算
	fmt.Println(utf8.RuneCountInString("ab")) //2
	fmt.Println(utf8.RuneCountInString("你好")) //2

	//字节视角的迭代，使用 for
	var sa = "中国人"
	for i := 0; i < len(sa); i++ {
		fmt.Printf("index: %d, value: 0x%x\n", i, sa[i])
	}
	fmt.Println()

	//字符串中 Unicode 字符的码点值，使用 for ... range
	var sc = "中国人"
	for i, v := range sc {
		fmt.Printf("index: %d, value: 0x%x\n", i, v)
	}

	//字符串与字节切片、字符串与 rune 切片的双向转换
	var sx string = "中国人"
	// string -> []rune
	rs := []rune(s)
	fmt.Printf("%x\n", rs) // [4e2d 56fd 4eba]
	// string -> []byte
	bs := []byte(sx)
	fmt.Printf("%x\n", bs) // e4b8ade59bbde4baba
	// []rune -> string
	sx1 := string(rs)
	fmt.Println(sx1) // 中
	// []byte -> string
	sx2 := string(bs)
	fmt.Println(sx2) // 中国人

	//字符串拼接,用 + 号
	sk1 := "你好"
	sk2 := "再见"
	fmt.Println(sk1 + sk2) //你好再见

	stringFn("A,B,C")
	stringConv()
	fmt.Println("---------")
	stringConv2()
}

/*字符串分割成数组，以及数组拼接成字符串*/
func stringFn(s string) {
	parts := strings.Split(s, ",")
	for _, part := range parts {
		fmt.Println(part)
	}
	fmt.Println(strings.Join(parts, "-"))
}

/*字符串和数字的转换*/
func stringConv() {
	s := strconv.Itoa(10)
	fmt.Println("str" + s)
	if i, err := strconv.Atoi("10"); err == nil {
		fmt.Println(10 + i)
	}
}

/*字符串转换成其它类型*/
func stringConv2() {
	var str string = "true"
	var b bool
	// b, _ = strconv.ParseBool(str)
	// 说明
	// 1. strconv.ParseBool(str) 函数会返回两个值 (value bool, err error)
	// 2. 因为只想获取到 value bool ,不想获取 err 所以使用_忽略
	b, _ = strconv.ParseBool(str)
	fmt.Printf("b type %T  b=%v\n", b, b) //b type bool  b=true

	var str2 string = "1234590"
	var n1 int64
	var n2 int
	n1, _ = strconv.ParseInt(str2, 10, 64)
	n2 = int(n1)
	fmt.Printf("n1 type %T  n1=%v\n", n1, n1) //n1 type int64  n1=1234590
	fmt.Printf("n2 type %T n2=%v\n", n2, n2)  //n2 type int n2=1234590

	var str3 string = "123.456"
	var f1 float64
	f1, _ = strconv.ParseFloat(str3, 64)
	fmt.Printf("f1 type %T f1=%v\n", f1, f1) //f1 type float64 f1=123.456

	var str4 string = "hello"
	var n3 int64 = 11
	n3, _ = strconv.ParseInt(str4, 10, 64)
	fmt.Printf("n3 type %T n3=%v\n", n3, n3) //n3 type int64 n3=0
}
